
#include <poll.h>
#include <sys/epoll.h>

#include "Channel.hpp"
#include "Logger.hpp"

namespace tulun
{
    // static const int kNew = -1;
    // static const int kAdded = 1;
    // static const int kDeleted = 2;
    // class EventLoop;
    // class Channel::
    // using EventCallback = std::function<void(void)>;
    // using ReadEventCallback = std::function<void(tulun::Timestamp)>;

    const int Channel::kNoneEvent = 0;
    const int Channel::kReadEvent = POLLIN | POLLPRI;
    const int Channel::kWriteEvent = POLLOUT;

    // EventLoop *loop_;
    // const int fd_;
    // int events_;
    // int revents_;
    // int index_;
    // std::weak_ptr<void> tie_;
    // bool tied_;
    // bool eventHeadling_;
    // bool addedToLoop_;
    // ReadEventCallback readCallback_;
    // EventCallback writeCallback_;
    // EventCallback closeCallback_;
    // EventCallback errorCallback_;

    void Channel::update()
    {
    }
    void Channel::handleEventWithGuard(const Timestamp &receiveTime)
    {
        eventHeadling_ = true;
        if ((revents_ & POLLHUP) && !(revents_ & POLLIN))
        {
            if (closeCallback_)
            {
                closeCallback_();
            }
        }
        if (revents_ & POLLNVAL)
        {
            LOG_WARN << "Channel::handle_event() POLLNAVL";
        }
        if (revents_ & (POLLERR | POLLNVAL))
        {
            if (errorCallback_)
            {
                errorCallback_();
            }
        }
        if (revents_ & (POLLIN | POLLPRI | POLLHUP))
        {
            if (readCallback_)
            {
                readCallback_(receiveTime);
            }
        }
        if (revents_ & (POLLOUT))
        {
            if (writeCallback_)
            {
                writeCallback_();
            }
        }
        eventHeadling_ = false;
    }

    void Channel::handleEvent(const Timestamp &receiveTime)
    {
        handleEventWithGuard(receiveTime);
    }
    Channel::Channel(EventLoop *loop, int fd)
        : loop_(loop),
          fd_(fd),
          events_(0),
          revents_(0),
          index_(-1),
          tied_(false),
          eventHeadling_(false),
          addedToLoop_(false)
    {
    }
    Channel::~Channel()
    {
    }
    void Channel::remove()
    {
    }
} // namespace tulun